package Testdemo3.Test1;

import  java.util.*;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User:周次煜
 * Date: 2024-05-14
 * Time：23:22
 */


public class Test2 {
    public static void main1(String[] args) {

        /**
         * Java 中 取模 得到的正负
         * 主要看 第一个值 的正负来决定
         */

        System.out.println("=========初始结果=======");
        System.out.println(-7 % 2); // 负数


        System.out.println(7 % -2); // 正数

        System.out.println(-7 % -2); // 负数

        System.out.println("=========调整后的结果=======");

        /**
         * 调整方法
         * (a % k + k ) % k
         *
         * 相当于 对第一个 被取模的元素进行  去负号 操作
         */



        System.out.println( ( (-7 % 2 )+ 2 ) % 2); // 相当于 7 % 2

        System.out.println( (( 7 % -2) + -2 ) % -2 ); // 想到于 还是 7 % -2

        System.out.println( ((-7 % -2) + -2)  % -2 ); // 相当于 是 7 % -2

    }






    public static int findMaxLength(int[] nums) {

        int n= nums.length;
        // 定义个哈希表
        // 左边为前缀和 ， 右边 为 下标位置
        Map<Integer , Integer> map= new HashMap<>();
        int len=0,sum = 0;
        int [] f= new int[n];

        // 把 0 的值全部改成 -1；
        for(int i=0 ; i < n; ++i ) {
            if(nums[i]==0) {
                f[i]= -1;
            } else {
                f[i] = 1;
            }
        }

        map.put(0,0);

        // 前缀和 + 哈希表
        for(int j=0; j < n ; j++) {

            // 进行前缀和
            sum += f[j];

            // 更新结果
            int t = j - map.getOrDefault(0, j+1);
            len= Math.max(len,t+1);

            // 讲 前缀和放入 哈希表
            map.put(sum,j);
        }

        return len;

    }


    public static void main(String[] args) {
        int [] array= {0,1,0};
        System.out.println(findMaxLength1(array));
    }


    /**
     * 计算连续子数组的长度
     * 该子数组中只包含 0 或 1 的值
     *  利用 前缀和
     * @param nums
     * @return
     */

    public static int findMaxLength1(int[] nums) {

        int n= nums.length;
        // 定义个哈希表
        // 左边为前缀和 ， 右边 为 下标位置
        Map<Integer , Integer> map= new HashMap<>();
        int len=0,sum = 0;
        int [] f= new int[n];

        // 把 0 的值全部改成 -1；
        for(int i=0 ; i < n; ++i ) {
            if(nums[i]==0) {
                f[i]= -1;
            } else {
                f[i] = 1;
            }
        }


        map.put(0,-1);

        // 前缀和 + 哈希表
        for(int j=0; j < n ; j++) {

            // 进行前缀和
            sum += f[j];

            // 更新结果
            int t = j - map.getOrDefault(sum, j);
            len= Math.max(len,t);

            // 讲 前缀和放入 哈希表
            if(!map.containsKey(sum))
                map.put(sum,j);
        }

        return len;

    }

    public int findMaxLength2(int[] nums) {

        int n= nums.length;
        // 定义个哈希表
        // 左边为前缀和 ， 右边 为 下标位置
        Map<Integer , Integer> map= new HashMap<>();
        int len=0,sum = 0;



        map.put(0,-1);

        // 前缀和 + 哈希表
        for(int j=0; j < n ; j++) {

            // 进行前缀和
            sum +=  (nums[j]==0 ? -1 : 1) ;


            // 这个本质上还是相当于 用 getOrdefault() 来判断

            // 更新结果
            if(map.containsKey(sum)) {

                len=Math.max(len,j - map.get(sum) );
            } else {
                // 如果不存在该前缀和 就 进行哈希表

                // 这里的细节就是
                // 不需要进入重复元素
                map.put(sum,j);

            }
        }

        return len;

    }

    /**
     * 矩阵区域和
     *
     * 二维矩阵前缀和
     *
     * 细节一： 主要 原始矩阵是 从 0 需要 x - 1 , y - 1
     *
     * 细节二 : 下标越界时， 需要把 越界的下标 赋值为 边界下标
     *
     * @param mat 目标数组
     * @param k 扩展的单位
     * @return 返回  每个中心位置扩展区域的 总和 的矩阵
     */


    public int[][] matrixBlockSum(int[][] mat, int k) {
        int n= mat.length;
        int m= mat[0].length;

        // 定义一个返回数组
        int[][] ret= new int[n][m];




        int[][] dp= new int[n+1][m+1];

        // 进行前缀和
        for(int i = 1; i < n+1; i++ ) {
            for(int j=1; j < m+1 ; j++ ) {
                // 注意这个是加上左上角的数值
                // i-1
                // j-1
                dp[i][j]= dp[i-1][j] + dp[i][j-1] + mat[i-1][j-1]-
                        dp[i-1][j-1];
            }
        }

        for(int i = 1; i < n+1 ; i++) {


            for(int j=1; j < m+1; j++ ) {

                // 下标转化
                // 防止越界
                int x1 = i-k , y1= j - k  ,x2 = i + k, y2= j + k;

                if(x1 < 1) x1 = 1;
                if(y1 < 1) y1 = 1;
                if(x2 > n) x2 = n;
                if(y2 > m) y2 = m;

                // 更新结果
                ret[i-1][j-1] = dp[x2][y2] - dp[x2][y1-1]
                        - dp[x1-1][y2] + dp[x1-1][y1-1];
            }



        }

        return ret;

    }

}
